package com.jml.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Proxy;


@Component
@Slf4j
public class FeignClientProxy {
    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RotationLoadBalancerClient rotationLoadBalancerClient;
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    /**
     * jdk动态代理模式+反射+ribbon负载均衡器实现
     */
    public <T> T create(Class<T> tClass) {
        return (T) Proxy.newProxyInstance(tClass.getClassLoader(), new Class[]{tClass}, (proxy, method, args) -> {
            //1.获取MemberServiceFeign类上的@FeignClient 的value 服务名称  @JmlFeignClient(value = "jml-member")
            JmlFeignClient jmlFeignClient = tClass.getDeclaredAnnotation(JmlFeignClient.class);
            String serviceName = jmlFeignClient.value();
            if (StringUtils.isEmpty(serviceName)) {
                throw new Exception("没有指定该接口的服务名称");
            }

//            //2.根据服务名称 从nacos上获取接口地址
//            List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
//            /**
//             * 负载均衡算法
//             * 轮询
//             * 故障转移
//             * 随机
//             */
//            //3.获取到接口地址有可能是多个 在采用负载均衡算法 取出一个地址
////            ServiceInstance serviceInstance = instances.get(0);
//            ServiceInstance serviceInstance = rotationLoadBalancerClient.getSingleAddress(instances);
            ServiceInstance serviceInstance = loadBalancerClient.choose(serviceName);
            //4.使用rest模板的方式实现rpc远程调用
            RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
            String interfaceName = requestMapping.value()[0];
            // 192.168.110.1:8081/getUser
            String rpcAddres = serviceInstance.getUri() + interfaceName;
            log.info(">>>reqestAddres>>>=" + rpcAddres);
            Object result = restTemplate.getForObject(rpcAddres, method.getReturnType());
            log.info(">>>respResult>>>=" + result);
            return result;
        });
    }
}
